package Decorator;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;

import pyrachnid.model.ground_model.Cell;
import pyrachnid.model.ground_model.Fire;
import pyrachnid.model.ground_model.Map;
import pyrachnid.model.robot_model.Manager;
import pyrachnid.model.robot_model.Robot;
import pyrachnid.model.robot_model.RobotType;
import pyrachnid.model.scenar_model.Scenario;
import pyrachnid.view.MainWindow;

public class MapBase extends Item {
	protected BufferedImage _image;
	protected BufferedImage _scaledImage;
	protected String _savePath;
	protected int _imageWidth = 0;
	protected int _imageHeight = 0;
	protected int _XNumber = 0;
	protected int _YNumber= 0;
	protected Map _map;
	protected ArrayList<Robot> _robots;
	private Panneau _panel;
	private boolean _imageIsLoad = false;

	// Constante
    private static final short ROBOT_ELEMENT = 0;
	private static final short FIRE_ELEMENT = 1;
	
	public MapBase(Panneau pan) {
		super(pan);
		_panel = pan;
	}

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if ( _scaledImage != null ) {
            g.drawImage(_scaledImage, 0, 0, _panel);
        }
    }
	

    /** Load Image **/
    
    public void loadImage(Scenario  p_scenario) throws IOException {
    	_map = p_scenario.getMap();
    	_robots = p_scenario.getRobotList();
    	_savePath = p_scenario.getMapPath();
    	
        _XNumber = (int) _map.getXdimension();
        _YNumber = (int) _map.getYdimension();
        
        _image = ImageIO.read(new File(_savePath));
        
        _imageWidth = _image.getWidth(_panel);
        _imageHeight = _image.getHeight(_panel);
        
        setScaledImage();
        //generateGrid();
		
        this.paintComponent(_panel.getGraphics());
        
        _imageIsLoad = true;	
    }
    
    public void removeImage(){
    	_imageIsLoad = false;
    	_map = null;
    	if(_robots != null)
    		_robots.removeAll(_robots);
    	_savePath = "";
    	_XNumber = 0;
    	_YNumber = 0;
    	if(_image != null)
    		_image.flush();
    	_imageWidth = 0;
    	_imageHeight = 0;
    	this.paintComponent(_panel.getGraphics());
    }

    /** Tool **/
    
    
    public boolean imageIsLoad()
    {
    	return _imageIsLoad;
    }

	

    /** Grid image **/
    
	@SuppressWarnings("unused")
	private void generateGrid() {
		double x = _imageWidth / _XNumber;
		double y = _imageHeight / _YNumber;
		int taillTrait = 2;
		
		Graphics g = _image.getGraphics();
		g.setColor(Color.WHITE);
		
		for(int i = 1; i < _XNumber; i++)
		{
			int coord = (int)(i * x);
			g.fillRect(coord, 0, taillTrait, _imageHeight);
		}

		for(int i = 1; i < _YNumber; i++)
		{
			int coord = (int)(i * y);
			g.fillRect(0, coord, _imageWidth, taillTrait);
		}
	}
	

    /** Scale Image **/

    public void scaleImage() {
        setScaledImage();
    }

    private void setScaledImage() {
        if ( _image != null ) {
            float iw = _imageWidth;
            float ih = _imageHeight;
            float pw = _panel.getWidth();   //panel width
            float ph = _panel.getHeight();  //panel height

            //to preserve image ratio
            if ( (pw / ph) > (iw / ih) ) {
                iw = -1;
                ih = ph;
            } else {
                iw = pw;
                ih = -1;
            }

            //prevent errors if panel is 0 wide or high
            if (iw == 0) {
                iw = -1;
            }
            if (ih == 0) {
                ih = -1;
            }

            _scaledImage = toBufferedImage(_image.getScaledInstance(
                        new Float(iw).intValue(), new Float(ih).intValue(), Image.SCALE_DEFAULT));
        }
    }

	

    
    /** Drag'n'Drop **/
    
    /**
     * Fonction d'ajout d'un nouvel �l�ment � la carte en fonction de la constante retourn�e
     * 
     * @param p_typeElement
     */
    public void addNewElement(short p_typeElement) {
    	
    	double mousePosX = _panel.getMousePosition().getX();
    	double mousePosY = _panel.getMousePosition().getY();
    	
    	double x = _scaledImage.getWidth(_panel) / _XNumber;
    	double y = _scaledImage.getHeight(_panel)/ _YNumber;
    	
    	int posX = (int) Math.floor(mousePosX/x) ;
    	int posY = (int) Math.floor(mousePosY/y) ;
    	
    	if(posX < Manager.getInstance().getMap().getXdimension() && posY < Manager.getInstance().getMap().getYdimension())
    	{
	    	if(ROBOT_ELEMENT == p_typeElement) {
	    		MainWindow mainWin = (MainWindow)((JRootPane)((JLayeredPane)((JPanel)_panel.getParent()).getParent()).getParent()).getParent();    		
	    		RobotType robotType = (RobotType)mainWin.getCb_robotTypeChooser().getSelectedItem();
	    		Robot robot = new Robot(posX,posY,robotType);
	    		_panel.addRobotImage(robot);
	    		((MainWindow)((JRootPane)((JLayeredPane)(_panel.getParent()).getParent()).getParent()).getParent()).getSimulator().getSenario().addRobot(robot);	
	    	} else if (FIRE_ELEMENT == p_typeElement) {
	    		Cell cell = _map.getGround()[posX][posY];
	    		cell.setFire(new Fire(40));
	    	}
    	}
    }
 // This method returns a buffered image with the contents of an image
    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage)image;
        }

        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();

        // Determine if the image has transparent pixels; for this method's
        // implementation, see Determining If an Image Has Transparent Pixels
        boolean hasAlpha = hasAlpha(image);

        // Create a buffered image with a format that's compatible with the screen
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            // Determine the type of transparency of the new buffered image
            int transparency = Transparency.OPAQUE;
            if (hasAlpha) {
                transparency = Transparency.BITMASK;
            }

            // Create the buffered image
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }

        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            if (hasAlpha) {
                type = BufferedImage.TYPE_INT_ARGB;
            }
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }

        // Copy image to buffered image
        Graphics g = bimage.createGraphics();

        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }
 // This method returns true if the specified image has transparent pixels
    public static boolean hasAlpha(Image image) {
        // If buffered image, the color model is readily available
        if (image instanceof BufferedImage) {
            BufferedImage bimage = (BufferedImage)image;
            return bimage.getColorModel().hasAlpha();
        }

        // Use a pixel grabber to retrieve the image's color model;
        // grabbing a single pixel is usually sufficient
         PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
        }

        // Get the image's color model
        ColorModel cm = pg.getColorModel();
        return cm.hasAlpha();
    }
}
